The chapter discusses the performance characteristics of the Oracle Retail RIB, the factors that affect it, and a process to test it.
Performance of the RIB within a customer site is critical to the performance of the business, and is determined by factors that are very specific to a given deployment. Because of this is, it is recommended by Oracle Retail that a Performance Test be part of every deployment plan. Even if formal testing is not planned, the use of the tools and processes discussed can measure the relative performance of the RIB sub-system and can be used to diagnose bottlenecks.
It is beyond the scope of this document to discuss all of the tools and techniques available at the host, network, database, and application server level.
See Also: RIB Implementation Guide.
The performance of each of these components is influential in the overall performance of the system:
The Application Server(s) topology and configuration.
The RIB deployment approach.
The hardware sizing and configuration of the RIB hosts.
The hardware sizing and configuration of the applications that are connected to the RIB.
The hardware sizing and configuration of the JMS provider host.
The hardware sizing and configuration of the RIB Hospitals hosts.
There are other factors that determine the performance of the overall system. Some of these factors in a RIB environment are:
Number of channels configured
Number of messages present in the topic
Size of the message
Database clustering
Application Server topology
Number of TAFRs in the processing of the message
Message aggregation
Each of the RIB Message Family volume requirements is almost always described for the end-to-end message flow. This is defined as from the publication to the completion of subscription by all Oracle Retail applications. Retail businesses express volume requirements in terms of details per hour and per day.
Each Message Family has different volume requirements and any given family may have an intermediate component between the originating publication and the end subscriber. These components are called TAFRs (Message Transform, Filtering and Routing). This is an important concept, since it means that in a given flow, a message published by the source system may be subscribed to and then re-published by a TAFR before it is subscribed to by the destination application. This is true in many of the Message Families.
Example Volume Requirements:
Family | Details Per Day | Details Per Hour |
---|---|---|
Purchase Orders |
355,000 |
355,000 |
ASN Inbound |
19,200,000 |
19,200,000 |
Appointments |
240,000 |
30,000 |
PO Receipt |
240,000 |
30,000 |
Store Receipt |
4,000,000 |
2,000,000 |
Transfers |
1,000,000 |
250,000 |
Stock Order Allocation |
600,000 |
75,000 |
Stock Order Transfer |
1,000,000 |
75,000 |
Stock Order Status |
600,000 |
75,000 |
ASN Outbound (BOL) |
285,000 |
285,000 |
Promotions |
5,000,000 |
250,000 |
Item Locations |
1,000,000 |
300,000 |
Items |
100,000 |
20,000 |
Note: These examples are for illustration, but are representative of actual customer requirements. |
Message construction is the same for all Oracle Retail Publishing applications and RIB adapters. There are configuration control points that allow flexibility in the size of the message. The application side has the ability to specify the number of details per message. The RIB has a setting that controls the aggregation of the messages (ribMessage) within the larger RibMessages envelope. There is a setting that controls the number of RibMessages published within a commit to the JMS.
See: "Message Aggregation".
The RIB is designed to support parallel message handling to increase through-put via a mechanism call multi-channel. Multi-channel is a concept to logically partition the flow of messages within the JMS topic so that multiple publishers and subscribers can simultaneously use the same JMS topic without any contention or interference with each other and preserve publication message ordering within the logical channel.
Every adapter instance of a publisher, subscriber, or TAFR, configured in the RIB is considered to belong to a logical channel for processing messages. By multi-channel adapters, we mean multiple adapter instances for the same message family, each processing messages asynchronously and in parallel. When multiple channels are used, they must be defined and configured across all publisher, subscriber, and TAFRs that participate in an end-to-end message flow to and from all Oracle Retail applications for that message family.
Each messaging RIB component involved in publishing or subscribing to a logical channel is distinctly identified by a JMS Message property known as "threadValue" with a specific value. This JMS message property and the value it contains define the logical channel.
JMS Message properties are user-defined additional properties that are included with the message. Message properties have types, and these types define application-specific information that message consumers can use to select the messages that interest them. Each RIB subscriber has the "threadValue" property and this value is part of its JMS Durable Subscriber selector and each RIB publisher sets the "threadValue" JMS message property to a specific value for each message it publishes.
Oracle Retail RIB components are capable of being multi-channeled by making configuration changes to the system. The base RIB configuration, as shipped GA, provides each Message Family with one channel where all components set or look for "threadValue" of 1 (one). The naming convention and the RIB kernel code identify the RIB adapters by adding the logical channel to the end of the adapter class name.
The example diagram demonstrates the multi-channeling of the Purchase Order flow to 2 channels.
As mentioned, the RIB's performance is judged by the average time a Message Family detail takes to flow from a publisher to consumption by all active subscribers. This is not a straight forward measurement.
Message through-put is not a calculation of the sum of the individual message times. Although the average time per message will remain fixed, messages are processed in parallel. So the total time to process n messages on a single channel will not be the serial sum of the individual messages.
Additionally, it is possible to configure multiple logical channels to increase overall through-put.
It is important to understand the average messages in an integration flow. In the RIB where interfaces are separated into messages families with differing payloads per type of message, these calculations can be difficult. This section outlines an approach for arriving at averages using the sample XML files that ship with the RIB.
The RIB delivers sample files generated for each Message Family that contains all elements for a message type and payload with all possible characters for each element.
Note: Several Families have variable types of "details" per header so a close investigation is required to understand what the relationship is and what a representative message can be. |
In practice, of course, this size will vary depending on the number of characters that a description element may contain, but for performance testing calculations, this is a reasonable start for calculations.
Note: An alternative is to use the audit feature of the RIB. These messages can then be used to estimate the average sizes. |
The RIB message envelope, called a RibMesssages contains a variable number of ribMessage nodes. Within a ribMessage node is a Message Family payload. A minimum payload for this exercise is defined as one header and a variable number of details.
The general process to determine the size in bytes of a Message Family message per detail using the RIB sample xml messages and xsds is as follows:
Determine the RIB envelope size (RibMessages elements + ribMessage elements)
Determine the size of a single header
Determine the size of a detail
The RIB has a standard message envelope (RIBMessages.xsd) that can be easily calculated exclusive of the message family payload:
ribMessage header elements no payload | 823 Bytes |
RibMessages header elements | 324 Bytes |
RibMessages with 1 rM no payload | 1147 Bytes |
Each message family is comprised of message type and an associate payload (e.g. POCre uses PODesc.xsd). These relationships are defined in the RIB Integration Guide.
The sample XML messages for each release are packaged in the functional artifacts war file and with RDMT in the rib-home/tools-home/rdmt/testmsgs directory.
Select the message payload file and look at the byte count. This will always be 1 header and 1 detail(s). Be aware that this relationship will vary by family and can be complex for some message types (e.g. ItemCre and ItemDesc.xsd) where optional details can be present.
Select the payload file and remove all detail nodes and look at the byte count. This will be the standard header. Use the same procedure for the detail(s). This will be the detail size.
Example Message - PODesc | |
Header Size (PODesc no detail) | 9413 |
1 Detail Size (PODtl) | 1943 |
The next step is to determine the average number of details per message. This will vary based on the business needs and the RIB configuration that is selected.
See: "Message Aggregation".
Using the desired number of details per message, this calculation is the result:
Total 1 RibMessages + 1 ribMessage + 1 Header + 1 Detail | Avg Message Size |
For Example:
Total 1 RibMessages + 1 ribMessage + 1 PODesc + 1 PODtl | 12,053 |
ribMessage header elements no payload |
823 |
RibMessages header elements |
324 |
RibMessages with 1 rM no payload |
1147 |
Message - PODesc |
|
Header Size (PODesc no detail) |
9413 |
1 Detail Size (PODtl) |
1943 |
Total 1 RibMessages + 1 ribMessage + 1 PODesc + 1 PODtl |
12,053 |
An example using the default settings; the RIB messages created by the Order publishing adapter for details per message:
Contains a maximum of 20 ribMessages per RibMessage
With 20 details per PODesc payload in a ribMessage
So for a 400 Details PO Message the calculation is:
RibMessage = 1 RibMessages header + 20 ribMessage headers + 20 PODesc + 400 PODtls
# ribMessage nodes |
20 |
# Details |
400 |
RibMessages Header (1) |
324 |
ribMessage Header (20) |
16,460 |
PODesc (20) |
188,260 |
PODtl (400) |
777,200 |
Total Bytes/Msg |
982,644 |
Using the example volume requirement for the Purchase Orders using the same RIB message configuration settings:
Details per hour requirement (Total Through-put) |
355,000 |
Details per Message |
400 |
Total messages per hour (355,000/400) |
887 |
Message/sec required (982 KB each - 60*60/887) |
4.058 |
So:
End-to-End — 1 message with 400 details can take a max of 4.058 seconds.
End-to-End — 982,644 Bytes can take a max of 4.058 seconds (which in this example is 400 details).
So:
982644 Bytes/4.058 sec = 242149.83 bytes/sec = 0.2421498 MB/sec Total end-to-end throughput to meet the Purchase Order example requirements.
These are end-to-end processing time requirements across the entire message flow from Publisher to Subscription completion.
To continue the Purchase Order example, the requirements and timings have to be broken down further. The Purchase Order flow has a TAFR as well as multiple subscribers. For purposes of this example, consider the Subscribers Consume times as equivalent. As the diagram depicts, for a flow like the Purchase Orders, there are multiple components and for a single message to flow there will be, at a minimum, a message published twice and subscribed twice, as well as a marshalling and un-marshalling of the message twice (Family dependent). There will be at least one, and possibly two, Hospital Dependency checks as well.
The performance of the RIB is a complicated subsystem to measure and involves not only host level performance, but database, network, and application server subsystems performance. To make measurement of the RIB components timing characteristics available for analysis, the RIB kernel code has been instrumented to log events as it processes events. The logging of these events is though log4j. The timings are logged per adapter. Once the timings are enabled the events are logging continuously to the file. The RIB RDMT supplies a post-processing tool to take the timing file and produce summary reports.
This table lists the currently pre-defined times that are tracked in the RIB Timings logs. The description is the definition of interval calculation.
Timing Type | Description | |
---|---|---|
T1 | PUB_B4_GETNXT_CALL | Time interval between start of the publisher and the actual GETNXT call. |
T2 | PUB_TIME_IN_GETNXT_CALL | Time taken by the GETNXT call to the plsql app. |
T3 | PUB_TIME_IN_EJB_PUBLISH_CALL | Time taken for the publish call in the EJB, includes RIB overhead surrounding the actual publish to the JMS. |
T4 | PUB_TOTAL_PUBLISH_TIME | Time taken for the complete PUB process = GETNXT + hospital dependency + publish + commit. |
T5 | PUB_TIME_IN_REAL_JMS_PUBLISH | Time taken to publish a message to the AQ JMS. |
T6 | SUB_TIME_IN_CONSUME_CALL | Time taken by the CONSUME call to the plsql app. |
T7 | SUB_TOTAL_SUBSCRIBE_TIME | Time taken for the complete SUB process = CONSUME/INJECT + hospital dependency + subscribe + commit. |
T8 | SUB_TIME_IN_EJB_SUBSCRIBE_CALL | Time taken for the subscribe call in the EJB, includes RIB overhead surrounding the actual subscribe. |
T9 | SUB_TIME_IN_INJECT_CALL | Time taken by the INJECT call to the java app. |
T10 | TAFR_TOTAL_MSGPROCESS_TIME | Time taken in the complete message tafring Process = TAFRing + hospital dependency + publish + RIB overhead. |
T11 | TAFR_TIME_IN_EJB_CALL | Time taken for the TAFR call in the EJB, includes RIB overhead surrounding the actual TAFRing. |
T12 | TAFR_TIME_IN_REAL_JMS_PUBLISH_EJB | Time taken by the TAFR to publish a message to the AQ JMS. |
Note: These are examples for illustration of the process and concepts, not test results. |
Order_pub_1 (Publisher)
TIMING_TYPE | COUNT | AVERAGE | TIME _SUM | MIN_TIME | MAX_TIME |
---|---|---|---|---|---|
PUB_B4_GETNXT_CALL | 100 | 0.03787 | 3.7904 | 0.036 | 0.07 |
PUB_TIME_IN_GETNXT_CALL | 100 | 0.06546 | 6.5528 | 0.061 | 0.254 |
PUB_TIME_IN_EJB_PUBLISH_CALL | 100 | 0.04192 | 4.1961 | 0.039 | 0.308 |
PUB_TOTAL_PUBLISH_TIME | 100 | 0.19675 | 19.6947 | 0.186 | 2.738 |
PUB_TIME_IN_REAL_JMS_PUBLISH_EJB | 100 | 0.02931 | 2.9341 | 0.027 | 0.292 |
OrderToOrderTafr_1 (TAFR)
TIMING_TYPE | COUNT | AVERAGE | TIME _SUM | MIN_TIME | MAX_TIME |
---|---|---|---|---|---|
TAFR_TOTAL_MSGPROCESS_TIME | 100 | 1.58708 | 158.708 | 1.296 | 4.135 |
TAFR_TIME_IN_EJB_CALL | 100 | 1.51371 | 151.371 | 1.23 | 3.24 |
TAFR_TIME_IN_REAL_JMS_PUBLISH_EJB | 100 | 1.1802 | 118.02 | 0.914 | 2.414 |
Order_sub_1
TIMING_TYPE | COUNT | AVERAGE | TIME _SUM | MIN_TIME | MAX_TIME |
---|---|---|---|---|---|
SUB_TIME_IN_CONSUME_CALL | 100 | 1.359 | 135.9 | 0.671 | 2.203 |
SUB_TOTAL_SUBSCRIBE_TIME | 100 | 1.93943 | 193.943 | 0.718 | 5.593 |
SUB_TIME_IN_EJB_SUBSCRIBE_CALL | 100 | 1.92386 | 192.386 | 0.687 | 5.593 |
So in this example, to describe the serial processing through-put time to Publish 100 messages through the TAFR to Subscriber Consume:
Publisher (19.69 Sec) + TAFR (158.708 sec) + Subscriber (193.943 sec) = 372.341 seconds = Average 3.72 msg/sec
It is important to understand that the actual message through-put is not a calculation of the sum of the individual message times. Although the average time per message will remain fixed, messages are processed in parallel. So the total time to process n messages on a single channel will not be the serial sum of the individual messages.
Note: This is an illustration. The number of message needed to arrive at a calculation of through-put would require much higher counts and across a broad spectrum of time and system load. Other factors including average size of message used is also a determining variable. |
Every customer site has unique requirements and flows, so the ones to focus on will vary. However, there are ones that always make to the list.
ASN
Receipts (PO and Store)
Promotions
Stock Order (Allocation & Transfers)
Item Locations
Items
It is strongly recommended that during the deployment planning phase, the business requirements for these and others be gathered and analyzed. Then plan some form of performance testing, even if only a characterization by measuring the actual flows during other test phases (e.g. Integration Test).
The Receipts Message Family is transactional data, and often a candidate for performance testing. Receiving consists of appointment and receipt messages that are published to the RIB for RMS providing open to buy visibility. An appointment is information about the arrival of merchandise at a location. A receipt message informs RMS when merchandise arrives in a warehouse or store system.
There are two distinct approaches to measuring RIB performance; using actual application end-points or using the RIB API simulators. Both are useful at different phases of deployment.
Keep in mind, that performance measuring is possible at any time in any phase, performance testing is more formal and requires planning, dedicated people and systems and test data. Building test data is difficult. Do not underestimate the complexity and this time consuming aspect of testing. To do testing with the applications involved, all of the data has to be consumable without errors.
There are tools available in RDMT to assist in this, as well as the audit feature of the RIB. By enabling audit on an interface all messages are saved to a file in a form that can be played back by RDMT utilities.
The API Simulators (PL/SQL and JavaEE) allow the focus to be on the RIB infrastructure and is possible without resources outside of the RIB team. The value is limited to profiling the deployment architecture independent of the application API behavior and is much simpler in terms of data generation.
The performance measures of the end-to-end flow using the application's API is the only way to match performance against requirements since the majority of the time spent in the flow is in the application API. Customers do not distinguish a separation between the RIB components and the application APIs.
The RIB supplied tools to support both forms of tests are the RIB Test Harness, the API simulators, and the RDMT tools; timing utility, JMS Publish and EJB Publish.
This is a general process on how to measure the flow end-to-end.
Prepare for the run.
Use RIB Admin GUI to stop all adapters (PUB, SUB, TAFR).
Use RDMT to archive all logs so that the run has clean logs.
Use RIB Admin GUI to enable timings logs (DEBUG) on all adapters.
Use RIB Admin GUI to set all other adapter logs to INFO.
Determine how to generate the messages.
Using the Oracle Retail Application (e.g. RMS to generate some orders).
Using RDMT EJB Publish (will use a portion of the PUB Adapter).
Using RDMT JMS Publish (will not use the PUB Adapter).
Start the appropriate adapters depending on the above decision.
Use RIB Admin GUI to start adapters (PUB, SUB, TAFR).
Generate the test messages.
Stop the adapters.
Analyze the data.
Use RDMT to run the Timing Analysis Utility on each adapter timing log. This will create a .csv file.
Upload the .csv files for display and further analysis using a tool such as Excel.
A channel is a solution approach to maintaining the previous RIB release concept of a "Logical Channel", also known as multi-threading.
Multi-channel is concept to logically partitioning the flow of messages within the JMS topic so that multiple publisher and subscriber can simultaneously use the same JMS topic without any contention or interference with each other and preserving publication message ordering within the logical channel.
Every adapter instance of a publisher, subscriber, or TAFR, configured in the RIB is considered to belong to a logical channel for processing messages. By multi-channel adapters we mean multiple adapter instances for the same message family, each processing messages asynchronously and in parallel.
There are critical rules of behavior that have to be observed and enforced to maintain the two primary RIB functional requirements of once-and-only-once successful delivery and guaranteed sequencing of messages within a message family.
To ensure that these rules are followed and to make the tasks of configuration of the RIB to support a multi-channel message flow as simple as possible, the process has been integrated into the RIB App Builder tools.
When multiple channels are being considered, they must be defined and configured across all publisher, subscriber, and TAFRs that participate in an end-to-end message flow to and from all Oracle Retail applications for that message family. The RIB App Builder tools have checks and verification logic to prevent deployment of incomplete flows.
Multi-channels can be a valuable tool to increase performance, but it does not help in every situation. There is overhead and complexity associated with implementing multiple channels so they should not be considered unless a defined and performance problem exists. The process of adding multi-channels to a message family should be part of a performance test and tuning process.
Each messaging RIB component involved in publishing or subscribing to a logical channel is distinctly identified by a JMS Message property known as "threadValue" with a specific value. This JMS message property and the value it contains define the logical channel.
JMS Message properties are user-defined additional properties that are included with the message. Message properties have types, and these types define application-specific information that message consumers can use to select the messages that interest them.
So each RIB subscriber has the "threadValue" property and this value as part of its JMS Durable Subscriber selector and each RIB publisher sets the "threadValue" JMS message property to a specific value for each message it publishes.
Oracle Retail RIB components are capable of being multi-channeled by making configuration changes to the system. The base RIB configuration, as shipped GA, provides each Message Family with one channel where all components set or look for "threadValue" of 1 (one). The naming convention and the RIB kernel code identify the RIB adapters by adding the logical channel to the end of the adapter class name.
Channels are calculated based on Business object ID(BOID) found in the RibMessages <id> tag. The algorithm used to calculate is as follows.
MOD(MD5(family + ":" + businessObjectId)%maxChannelNumber) + 1
First the algorithm calculates the message digest of the string family+":"+businessObjectId which produces a unique number.
Then this number is divided by the maxChannelNumber, which is calculated by the number of configured channels for that message family.
A 1 is added to the result so that the channel number is always greater than 0.
For example:
Family = Alloc BusinessObjectID (BOID) = 10202123 MaxChannelNumber = 7 (Total number of channels configured for the Alloc family) Then the channel number for the BOID is calculated as sMOD(MD5(Alloc + ":" + 10202123)%7) + 1 = 4 which means that all the messages that have BusinessObjectID of 10202123 are ALWAYS sent through channel 4 (Alloc_pub_4).
Note: The channels have to be configured throughout the integration flow using the rib-app builder tool. |
Example of a Message Family Flow with a TAFR:
Alloc_pub_1
Alloc_tafr_1
StockOrder_sub_1
Determine the Family to multi-channel
Examine the rib-integration-flows.xml to identify all participants in the full flow.
In the rib-home modify the appropriate configuration files for each of the rib-<apps>.
rib-<app>-adapters.xml
rib-<app>-adapter-resources.properties
For PL/SQL Application edit the RIB_SETTINGS table.
Compile and Deploy
This example is to configure the Alloc message flow with five channels. Alloc is a complex flow in that it has multiple Oracle Retail application subscribers and a TAFR that transforms the messages from one family to another; Alloc to StockOrder.
Backup the following files.
"rib-home/application-assembly-home/rib-rms/rib-rms-adapters.xml
rib-home/application-assembly-home/rib-rms/rib-rms-resources.properties.
The following is the message flow for the Alloc Family from rib-integration-flows.xml that this example uses.
<message-flow id="1"> <node id="rib-rms.Alloc_pub" app-name="rib-rms" adapter-class-def="Alloc_pub" type="DbToJms"> <in-db>default</in-db> <out-topic>etAllocFromRMS</out-topic> </node> <node id="rib-tafr.Alloc_tafr" app-name="rib-tafr" adapter-class-def="Alloc_tafr" type="JmsToJms"> <in-topic>etAllocFromRMS</in-topic> <out-topic name="topic-name-key-iso">etStockOrdersISO</out-topic> <out-topic name="topic-name-key-wh">etStkOrdersFromRIBToWH{*}</out-topic> </node> <node id="rib-sim.StockOrder_sub" app-name="rib-sim" adapter-class-def="StockOrder_sub" type="JmsToDb"> <in-topic>etStockOrdersISO</in-topic> <out-db>default</out-db> </node> <node id="rib-rwms.StockOrder_sub" app-name="rib-rwms" adapter-class-def="StockOrder_sub" type="JmsToDb"> <in-topic>etStkOrdersFromRIBToWH1</in-topic> <out-db>default</out-db> </node> </message-flow>
Modify rib-rms-adapters.xml to add multiple channels.
Following is a portion of rib-rms-adapters.xml
<publishers> <timer-driven id="Alloc_pub_1" initialState="running" timeDelay="10"> <timer-task> <class name="com.retek.rib.app.getnext.impl.GetNextTimerTaskImpl"/> <property name="maxChannelNumber" value="5" /> </timer-task> </timer-driven> <timer-driven id="Alloc_pub_2" initialState="running" timeDelay="10"> <timer-task> <class name="com.retek.rib.app.getnext.impl.GetNextTimerTaskImpl"/> <property name="maxChannelNumber" value="5" /> </timer-task> </timer-driven> <timer-driven id="Alloc_pub_3" initialState="running" timeDelay="10"> <timer-task> <class name="com.retek.rib.app.getnext.impl.GetNextTimerTaskImpl"/> <property name="maxChannelNumber" value="5" /> </timer-task> </timer-driven> <timer-driven id="Alloc_pub_4" initialState="running" timeDelay="10"> <timer-task> <class name="com.retek.rib.app.getnext.impl.GetNextTimerTaskImpl"/> <property name="maxChannelNumber" value="5" /> </timer-task> </timer-driven> <timer-driven id="Alloc_pub_5" initialState="running" timeDelay="10"> <timer-task> <class name="com.retek.rib.app.getnext.impl.GetNextTimerTaskImpl"/> <property name="maxChannelNumber" value="5" /> </timer-task> </timer-driven>
Modify rib-rms-adapter-resources.properties.
Alloc_pub_1.name=Alloc Publisher, channel 1 Alloc_pub_1.desc=Publisher for the Alloc family through channel 1. Alloc_pub_2.name=Alloc Publisher, channel 2 Alloc_pub_2.desc=Publisher for the Alloc family through channel 2. Alloc_pub_3.name=Alloc Publisher, channel 3 Alloc_pub_3.desc=Publisher for the Alloc family through channel 3. Alloc_pub_4.name=Alloc Publisher, channel 4 Alloc_pub_4.desc=Publisher for the Alloc family through channel 4. Alloc_pub_5.name=Alloc Publisher, channel 5 Alloc_pub_5.desc=Publisher for the Alloc family through channel 5.
Modify rib-tafr--adapters.xml to add channels for a family.
<tafrs> <message-driven id="Alloc_tafr_1" initialState="running" tafr-business-impl="com.retek.rib.domain.tafr.bo.impl.AllocToStockOrderFromRibBOImpl" /> <message-driven id="Alloc_tafr_2" initialState="running" tafr-business-impl="com.retek.rib.domain.tafr.bo.impl.AllocToStockOrderFromRibBOImpl" /> <message-driven id="Alloc_tafr_3" initialState="running" tafr-business-impl="com.retek.rib.domain.tafr.bo.impl.AllocToStockOrderFromRibBOImpl" /> <message-driven id="Alloc_tafr_4" initialState="running" tafr-business-impl="com.retek.rib.domain.tafr.bo.impl.AllocToStockOrderFromRibBOImpl" /> <message-driven id="Alloc_tafr_5" initialState="running" tafr-business-impl="com.retek.rib.domain.tafr.bo.impl.AllocToStockOrderFromRibBOImpl" />
Modify rib-tafr-adapters-resources.properties.
Alloc_tafr_1.name=AllocToStockOrder TAFR, channel 1 Alloc_tafr_1.desc=TAFR for converting Allocation messages to StockOrders and routing them to the correct warehouse or store system Alloc_tafr_2.name=AllocToStockOrder TAFR, channel 2 Alloc_tafr_2.desc=TAFR for converting Allocation messages to StockOrders and routing them to the correct warehouse or store system Alloc_tafr_3.name=AllocToStockOrder TAFR, channel 3 Alloc_tafr_3.desc=TAFR for converting Allocation messages to StockOrders and routing them to the correct warehouse or store system Alloc_tafr_4.name=AllocToStockOrder TAFR, channel 4 Alloc_tafr_4.desc=TAFR for converting Allocation messages to StockOrders and routing them to the correct warehouse or store system Alloc_tafr_5.name=AllocToStockOrder TAFR, channel 5 Alloc_tafr_5.desc=TAFR for converting Allocation messages to StockOrders and routing them to the correct warehouse or store system
Modify rib-sim-adapters.xml to add channels for a family.
<subscribers> <message-driven id="StockOrder_sub_1" initialState="running"/> <message-driven id="StockOrder_sub_2" initialState="running"/> <message-driven id="StockOrder_sub_3" initialState="running"/> <message-driven id="StockOrder_sub_4" initialState="running"/> <message-driven id="StockOrder_sub_5" initialState="running"/>
Modify rib-sim-adapters-properties.properties.
StockOrder_sub_1.name=StockOrder Subscriber, channel 1 StockOrder_sub_1.desc=Subscriber for the StockOrder family through channel 1. StockOrder_sub_2.name=StockOrder Subscriber, channel 2 StockOrder_sub_2.desc=Subscriber for the StockOrder family through channel 2. StockOrder_sub_3.name=StockOrder Subscriber, channel 3 StockOrder_sub_3.desc=Subscriber for the StockOrder family through channel 3. StockOrder_sub_4.name=StockOrder Subscriber, channel 4 StockOrder_sub_4.desc=Subscriber for the StockOrder family through channel 4. StockOrder_sub_5.name=StockOrder Subscriber, channel 5 StockOrder_sub_5.desc=Subscriber for the StockOrder family through channel 5.
Modify rib-rwms-adapters.xml to add channels for a family.
<subscribers> <message-driven id="StockOrder_sub_1" initialState="running"/> <message-driven id="StockOrder_sub_2" initialState="running"/> <message-driven id="StockOrder_sub_3" initialState="running"/> <message-driven id="StockOrder_sub_4" initialState="running"/> <message-driven id="StockOrder_sub_5" initialState="running"/>
Modify rib-rwms-adapters-properties.properties.
StockOrder_sub_1.name=StockOrder Subscriber, channel 1 StockOrder_sub_1.desc=Subscriber for the stockorder family through channel 1. StockOrder_sub_2.name=StockOrder Subscriber, channel 2 StockOrder_sub_2.desc=Subscriber for the stockorder family through channel 2. StockOrder_sub_3.name=StockOrder Subscriber, channel 3 StockOrder_sub_3.desc=Subscriber for the stockorder family through channel 3. StockOrder_sub_4.name=StockOrder Subscriber, channel 4 StockOrder_sub_4.desc=Subscriber for the stockorder family through channel 4. StockOrder_sub_5.name=StockOrder Subscriber, channel 5 StockOrder_sub_5.desc=Subscriber for the stockorder family through channel 5.
When a PL/SQL Publishing adapter is multi-channeled, the application code needs to designate the message to a specific thread. In order to do this, a change needs to be made in the RIB_SETTINGS table.
Find the Family of messages that is being multi-channeled, and adjust the column NUM_THREADS to the appropriate number. In this example, the number will be set to 4 for the Alloc Family.
In order to improve message publication throughput within the integration system, the RIB provides multiple capabilities. The easiest way to increase throughput of any system without much effort is to start working on the collection of data units instead of single data units. Using that philosophy, RIB provides capabilities to process the collection of multiple detail payloads in one transaction. To control the number of details (payload details) per payload header, the user needs to update the RIB_SETTING.MAX_DETAILS_TO_PUBLISH column in the PLSQL retail applications database schema. Another way to look at this same configuration is that it allows you to control the size of the payload that gets published within the RIB system.
Another level to increasing throughput capabilities that RIB provides is to aggregate messages in a transaction, i.e. bundle multiple payloads within a single message that gets published to the JMS server. Through message aggregation (<family>.maxNodesPerMessages), you can control the number of ribMessage nodes that gets bundled into a single RibMessages message. Different families can have different nodes per message so this property is qualified (prefixed) by the family name. This property allows you to control the overall size of the RibMessages xml message.
The third capability that RIB provides is to optimize/minimize XA transaction overhead by allowing the system to commit multiple RibMessages to the JMS server in a single 2 phase XA commit. The number of messages that will get committed to the JMS server in a single XA commit is controlled by the property named <family>.messagePerCommit. Different families might need different RibMessages per commit so this property is qualified (prefixed) by the family name.
The configurable properties (<family>.maxNodesPerMessages and <family>.messagePerCommit) applies to each individual rib-<app>. To update the property and propagate the configuration to the app server, edit the corresponding rib-<app>.properties in rib-home and redeploy the updated rib-<app>.
Bigger is not always better; the bigger the payload size, the bigger the memory requirement. A process (JVM) can get only so much of Operating System memory, if the size is too large it will run out of memory and you will get an OutOfMemoryError.
If lots of ribMessageNode are bundled into the same RibMessages message, a single failure in one of the ribMessage will rollback the full transaction which will 1) fill up your error hospital table and 2) decrease your throughput by many factors as now it has to go through the retry process.
The general best practice is don't prematurely optimize; test with your business data and, only if the default values are not meeting your business needs, think about optimization by updating these properties.
Edit the following file in rib-home:
rib-home/application-assembly-home/rib-<app>/rib-<app>.properties
Add the following properties:
<family>.maxNodesPerMessages=<your value>
<family>.MessagePerCommit=<your value>
Using the app-builder tool compile/deploy the application.
rib-app-compile.sh
rib-app-deployer.sh -deploy-rib-app-ear rib-<app>
Suppose there are 1300 payload details waiting to be published for a family. Suppose we have the following configuration in RIB:
MAX_DETAILS_TO_PUBLISH=100 maxNodesPerMessagess=5 MessagePerCommit=2
The diagram below explains the message aggregation in play in the RIB system. All the 1300 payload details will be published in 3 RibMessages within only two XA transaction commits. The first 2 RibMessages will have 5 ribMessage nodes each and each of the ribMessage node will have a payload with 100 payload details. Since in the example we have 1300 payload detail the 3rd RibMessages xml will have only 3 ribMessage node each with 100 payload details.
XA transaction 1 = (RibMessages1 + RibMessages2) RibMessages1 = ribMessage1 + ribMessage2 + ribMessage3 + ribMessage4 + ribMessage5. ribMessage1 = PayloadHeader + 100 * PayloadDetail ribMessage2 = PayloadHeader + 100 * PayloadDetail ….. ribMessage5 = PayloadHeader + 100 * PayloadDetail
RibMessages2 equivalent to RibMessages1
XA Transaction 2 = RibMessages3 RibMessages3 = ribMessage1 + ribMessage2 + ribMessage3
Total = (XA Transaction 1 + XA Transaction 2) 100*5 + 100*5 + 100*3 = 1300
The RIB supports configuration of hospital retry adapters specific to message families. The family based adapters are configured to address performance issues when the error hospital gets very large--and a single retry adapter cannot handle the load.
Errors during processing result in messages in the error hospital. Reasons for errors include the following:
Incomplete or partial data from RMS: In this case, the messages are inserted into the error hospital with a reason code of PUB.
JMS related publication error conditions: (For example, the JMS server is down or not available due to network failures.) In this case, the messages are inserted into the error hospital with a reason code of JMS.
The subscriber application is not able to consume the message: In this case, the messages are inserted into the error hospital with a reason code of SUB.
By default, there are three kinds of hospital adapters, as listed below:
Sub retry adapter
JMS retry adapter
Pub retry adapter (RMS is the only application for which the Pub retry adapter is required.)
The sub retry adapter retries only those messages with a reason code of SUB. Similarly, the JMS retry adapter and the Pub retry adapter retry messages with reason codes of JMS and PUB, respectively.
Note: For more information about the hospital retry mechanism, see the "RIB Hospital Retry" section of the RIB Implementation Guide. |
Each message in the error hospital belongs to a particular message family. When the error hospital has a large number of messages from different families, the retry process becomes a performance bottleneck, as the default retry adapters retry the messages one by one (in a first in, first out manner), irrespective of message family.
To alleviate a bottleneck situation, retry adapters can be configured for a specific family and reason code. A family retry adapter can coexist with the default retry adapters. However, the default retry adapters will not retry those messages for which family retry adapters have been configured.
A family based retry adapter retries messages only for the family and reason code for which it is configured. For example, if a retry adapter is configured for the Order family and the SUB reason code, it retries only those messages from the Order family that failed with a reason code of SUB.
For each message family, a maximum of three family retry adapters can be configured--one for each reason code (PUB, SUB, and JMS).
Process Overview:
Determine the rib-<apps> where the family specific hospital retry adapter is to be configured.
Determine the family for which the retry adapter should be configured.
Determine the reason code (for example, PUB, SUB, or JMS) for the family retry adapter.
In the rib-home, modify the appropriate configuration files for the rib-<apps>:
rib-<app>-adapters.xml
rib-<app>-adapter-resources.properties
Compile and deploy.
Example:
To configure a family specific adapter for the Order family, where reason code = SUB and application = rib-rms, complete the following steps:
Backup the following files:
rib-home/application-assembly-home/rib-rms/rib-rms-adapters.xml
rib-home/application-assembly-home/rib-rms-resources.properties
Modify rib-rms-adapters.xml to add the family specific hospital retry adapter. The following is a portion of rib-rms-adapters.xml:
<hospitals> <timer-driven id="Order_familysubhosp_0" initialState="stopped" timeDelay="10" > <timer-task> <class name="com.retek.rib.j2ee.ErrorHospitalRegryTimerTask"/> </timer-task> </timer-driven/> <hospitals>
Modify rib-rms-adapter-resources.properties as follows:
Order_familysubhosp_0.name=Order SUB Hospital Retry
Order_familysubhosp_0.desc=Inject messages into JMS from Error Hospital
Note: Only one instance of family retry adapter can be configured per family and per reason code. |
Compile and Deploy:
Using the RIB Installer or the RIB App Builder command line tools, compile and deploy the new rib-<app>.ears.